package org.jeecg.modules.common.baseservice;

import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.TenantContext;
import org.jeecg.modules.common.api.ISysInfo;
import org.jeecg.modules.common.baseentity.BaseApiEntity;
import org.jeecg.modules.common.utils.BeanObjUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class SysInfo implements ISysInfo {
    @Autowired
    private ISysBaseAPI sysBaseAPI;

    /**
     * 从 token 获取用户信息，组织信息
     *
     * @param token，必填
     * @param tenantId
     * @param schoolYearId
     * @param semesterId
     * @return
     */
    @Override
    public BaseApiEntity getBaseApiEntityByToken(String token,String tenantId,String schoolYearId,String semesterId){
        if(oConvertUtils.isEmpty(token) ){
            return null;
        }

        BaseApiEntity baseApiEntity = new BaseApiEntity();

        //获取当前登录用户信息
//        String token = req.getHeader(CommonConstant.X_ACCESS_TOKEN);
        String username = JwtUtil.getUsername(token);
        baseApiEntity.setUsername(username);
        baseApiEntity.setCreateBy(username);
        baseApiEntity.setUpdateBy(username);

        LoginUser loginUser = sysBaseAPI.getUserByName(username); //.getUserById() 获取登录用户
        baseApiEntity.setLoginUser(loginUser);
        String sysOrgCode = loginUser.getOrgCode();//获取当前用户的当前的部门编码（不是id是编码）,该编码随前端切换
//        String tenantId = oConvertUtils.isEmpty(req.getHeader("tenant-id")) ? TenantContext.getTenant() : req.getHeader("tenant-id");//获取当前登录用户的租户id


//        String schoolYearId = req.getHeader("school-year-id");//获取当前登录系统选择的学年 //例如：在字典查询时候的req的Header中不包含学期学年，无法赋值
//        String semesterId = req.getHeader("semester-id");//获取当前登录系统选择的学期 //例如：在字典查询时候的req的Header中不包含学期学年，无法赋值
        //如果参数不为空则设置值
        if(oConvertUtils.isNotEmpty(tenantId) ){
            baseApiEntity.setTenantId(tenantId);
        }
        if(oConvertUtils.isNotEmpty(schoolYearId) ){
            baseApiEntity.setSchoolYearId(schoolYearId);
        }
        if(oConvertUtils.isNotEmpty(semesterId) ){
            baseApiEntity.setSemesterId(semesterId);
        }


        String departId = sysBaseAPI.getDepartIdsByOrgCode(sysOrgCode);//获取当前用户设置的部门id
        List<String> subDepIdsList = sysBaseAPI.getSubDepIdsByDepId(departId); //获取下级部门的部门id，自定义改造sysBaseAPI

        baseApiEntity.setSysOrgCode(sysOrgCode);
        baseApiEntity.setSubDepIdsList(subDepIdsList);
        String subDepSysOrgCodes = sysBaseAPI.getSubDepOrgCodesByDepId(departId); //直接获取下级部门的orgcode，自定义改造sysBaseAPI
        baseApiEntity.setSubDepSysOrgCodes(subDepSysOrgCodes);
        //userIdentity 用户身份字典码user_identity， 3教师 4学生 1普通用户 2上级部门负责人 5家长 6班级
        int userIdentity = loginUser.getUserIdentity();//获取当前登录用户身份：字典码 user_identity
        baseApiEntity.setUserIdentity(userIdentity);

        return baseApiEntity;

    }

    /**
     * 从request获取 token 用户信息，组织信息
     *
     * @param req
     * @return
     */
    @Override
    public BaseApiEntity getBaseApiEntity(HttpServletRequest req){
        //获取当前登录用户信息
        String token = req.getHeader(CommonConstant.X_ACCESS_TOKEN);

        String tenantId = oConvertUtils.isEmpty(req.getHeader("tenant-id")) ? TenantContext.getTenant() : req.getHeader("tenant-id");//获取当前登录用户的租户id
        TenantContext.setTenant(tenantId);//重新设置租户id

        String schoolYearId = req.getHeader("school-year-id");//获取当前登录系统选择的学年 //例如：在字典查询时候的req的Header中不包含学期学年，无法赋值
        String semesterId = req.getHeader("semester-id");//获取当前登录系统选择的学期 //例如：在字典查询时候的req的Header中不包含学期学年，无法赋值

        return getBaseApiEntityByToken(token,tenantId,schoolYearId,semesterId);

    }
    /**
     * 从request获取 token 用户信息，组织信息
     *
     * @param req
     * @param objEntityOrVo
     * @return
     */
    @Override
    public BaseApiEntity querySysInfoCloneObj(HttpServletRequest req, Object objEntityOrVo) {

        BaseApiEntity baseApiEntity = getBaseApiEntity(req);
        //保留业务对象的原始值：从业务对象取值赋值给基础对象，确保后面反向赋值的时候不会覆盖为null,确保业务对象带有最初的原始值
        // 注意：尤其是baseApiEntity中没有而objEntityOrVo中有的值会被保留原来的值
        //例如：在字典查询时候的req的Header中不包含学期学年，无法赋值
//        BeanUtils.copyProperties(objEntityOrVo,baseApiEntity);
        BeanObjUtil.copyDeepCloneProperties(baseApiEntity,objEntityOrVo);//使用自定义防范，深度克隆复制数据值，合并成map再转obj，冲突时候以第2个参数为最终值(相同属性后赋值的是最终数据值）


        //获取当前登录用户信息
        String token = req.getHeader(CommonConstant.X_ACCESS_TOKEN);
        String username = JwtUtil.getUsername(token);
        baseApiEntity.setUsername(username);
        baseApiEntity.setCreateBy(username);
        baseApiEntity.setCreateUser(username);
        baseApiEntity.setCreateTime(new Date());
        baseApiEntity.setUpdateBy(username);
        baseApiEntity.setUpdateTime(new Date());
        baseApiEntity.setEditUser(username);
        baseApiEntity.setEditTime(new Date());

        LoginUser loginUser = sysBaseAPI.getUserByName(username); //.getUserById() 获取登录用户
        baseApiEntity.setLoginUser(loginUser);
        String sysOrgCode = loginUser.getOrgCode();//获取当前用户的当前的部门编码（不是id是编码）,该编码随前端切换
        String tenantId = oConvertUtils.isEmpty(req.getHeader("tenant-id")) ? TenantContext.getTenant() : req.getHeader("tenant-id");//获取当前登录用户的租户id
        TenantContext.setTenant(tenantId);//重新设置租户id

        String schoolYearId = req.getHeader("school-year-id");//获取当前登录系统选择的学年 //例如：在字典查询时候的req的Header中不包含学期学年，无法赋值
        String semesterId = req.getHeader("semester-id");//获取当前登录系统选择的学期 //例如：在字典查询时候的req的Header中不包含学期学年，无法赋值
        //优先使用业务对象接收到的参数：如果参数为空则从Header中获取并赋值，如果业务对象已经有原有的数据则不变更
        //防止误改
        if(oConvertUtils.isEmpty(baseApiEntity.getTenantId()) ){
            baseApiEntity.setTenantId(tenantId);
        }
        if(oConvertUtils.isEmpty(baseApiEntity.getSchoolYearId()) ){
            baseApiEntity.setSchoolYearId(schoolYearId);
        }
        if(oConvertUtils.isEmpty(baseApiEntity.getSemesterId()) ){
            baseApiEntity.setSemesterId(semesterId);
        }

//        TenantContext.setTenant(tenantId);//重新设置租户id

        String departId = sysBaseAPI.getDepartIdsByOrgCode(sysOrgCode);//获取当前用户设置的部门id
        List<String> subDepIdsList = sysBaseAPI.getSubDepIdsByDepId(departId); //获取下级部门的部门id，自定义改造sysBaseAPI
        if(oConvertUtils.isEmpty(baseApiEntity.getSysOrgCode()) ){
            baseApiEntity.setSysOrgCode(sysOrgCode);
        }
        if(oConvertUtils.isEmpty(baseApiEntity.getSubDepIdsList()) ){
            baseApiEntity.setSubDepIdsList(subDepIdsList);
        }

        String subDepSysOrgCodes = sysBaseAPI.getSubDepOrgCodesByDepId(departId); //直接获取下级部门的orgcode，自定义改造sysBaseAPI
        if(oConvertUtils.isEmpty(baseApiEntity.getSubDepSysOrgCodes()) ){
            baseApiEntity.setSubDepSysOrgCodes(subDepSysOrgCodes);
        }

        //userIdentity 用户身份字典码user_identity， 3教师 4学生 1普通用户 2上级部门负责人 5家长 6班级
        int userIdentity = loginUser.getUserIdentity();//获取当前登录用户身份：字典码 user_identity
        if(oConvertUtils.isEmpty(baseApiEntity.getUserIdentity()) ){
            baseApiEntity.setUserIdentity(userIdentity);
        }
        //给业务对象赋 创建人、修改人、部门编码的值:此处赋值不支持父级属性的赋值,且保留业务对象的原始值（尤其是baseApiEntity中没有而objEntityOrVo中有的值会被保留原来的值
//        BeanUtils.copyProperties(baseApiEntity,objEntityOrVo);//此处没有复制父类属性，无法设置tenantId属性值
        // 注意：尤其是baseApiEntity中没有而objEntityOrVo中有的值会被保留原来的值
        BeanObjUtil.copyDeepCloneProperties(objEntityOrVo,baseApiEntity);//使用自定义防范，深度克隆复制数据值，合并成map再转obj，冲突时候以第2个参数为最终值(相同属性后赋值的是最终数据值）
        //优先使用业务对象接收到的参数：如果参数为空则从Header中获取并赋值，如果业务对象已经有原有的数据则不变更
        //防止误改：原对象已完成赋值，修改baseApiEntity的环境属性，回归当前操作的环境变量实时数据值
        baseApiEntity.setTenantId(tenantId);
        baseApiEntity.setSchoolYearId(schoolYearId);
        baseApiEntity.setSemesterId(semesterId);
        baseApiEntity.setSysOrgCode(sysOrgCode);
        baseApiEntity.setSubDepIdsList(subDepIdsList);
        baseApiEntity.setSubDepSysOrgCodes(subDepSysOrgCodes);
        baseApiEntity.setUserIdentity(userIdentity);
        //属性存在且值为null,则赋值
        if(BeanObjUtil.isExistFieldNameIncludeFather("schoolYearId",objEntityOrVo.getClass()) && oConvertUtils.isEmpty(BeanObjUtil.getFieldValueByName(objEntityOrVo,"schoolYearId"))){
            BeanObjUtil.setFieldValueByName(objEntityOrVo,"schoolYearId",schoolYearId);
        };
        if(BeanObjUtil.isExistFieldNameIncludeFather("semesterId",objEntityOrVo.getClass()) && oConvertUtils.isEmpty(BeanObjUtil.getFieldValueByName(objEntityOrVo,"semesterId"))){
            BeanObjUtil.setFieldValueByName(objEntityOrVo,"semesterId",semesterId);
        };
        if(BeanObjUtil.isExistFieldNameIncludeFather("tenantId",objEntityOrVo.getClass()) && oConvertUtils.isEmpty(BeanObjUtil.getFieldValueByName(objEntityOrVo,"tenantId"))){
            BeanObjUtil.setFieldValueByName(objEntityOrVo,"tenantId",tenantId);
        };
        if(BeanObjUtil.isExistFieldNameIncludeFather("sysOrgCode",objEntityOrVo.getClass()) && oConvertUtils.isEmpty(BeanObjUtil.getFieldValueByName(objEntityOrVo,"sysOrgCode"))){
            BeanObjUtil.setFieldValueByName(objEntityOrVo,"sysOrgCode",sysOrgCode);
        };
        return baseApiEntity;
    }

    /**
     * 克隆对象属性并获得系统参数，从request获取 token 用户信息，组织信息,默认不含有用户基础信息
     *
     * @param req
     * @param objEntityOrVo
     * @return
     */
    @Override
    public BaseApiEntity querySysInfoCloneObj(HttpServletRequest req, Object objEntityOrVo,boolean objIncludeUserInfo ) {
        BaseApiEntity baseApiEntity = querySysInfoCloneObj( req,  objEntityOrVo);
        if(! objIncludeUserInfo){
            if(BeanObjUtil.isExistFieldNameIncludeFather("createBy",objEntityOrVo.getClass())){
                BeanObjUtil.setFieldValueByName(objEntityOrVo,"createBy",null);
            }
            if(BeanObjUtil.isExistFieldNameIncludeFather("createUser",objEntityOrVo.getClass())){
                BeanObjUtil.setFieldValueByName(objEntityOrVo,"createUser",null);
            }

            if(BeanObjUtil.isExistFieldNameIncludeFather("createTime",objEntityOrVo.getClass())){
                BeanObjUtil.setFieldValueByName(objEntityOrVo,"createTime",null);
            }
            if(BeanObjUtil.isExistFieldNameIncludeFather("updateBy",objEntityOrVo.getClass())){
                BeanObjUtil.setFieldValueByName(objEntityOrVo,"updateBy",null);
            }

            if(BeanObjUtil.isExistFieldNameIncludeFather("updateTime",objEntityOrVo.getClass())){
                BeanObjUtil.setFieldValueByName(objEntityOrVo,"updateTime",null);
            }
            if(BeanObjUtil.isExistFieldNameIncludeFather("editUser",objEntityOrVo.getClass())){
                BeanObjUtil.setFieldValueByName(objEntityOrVo,"editUser",null);
            }
            if(BeanObjUtil.isExistFieldNameIncludeFather("editTime",objEntityOrVo.getClass())){
                BeanObjUtil.setFieldValueByName(objEntityOrVo,"editTime",null);
            }
        }
        return baseApiEntity;
    }
    /**
     * 查询系统参数
     * @param userInfo
     * @return BaseApiEntity
     */
    @Override
    public BaseApiEntity querySysInfoByUser(SysUserCacheInfo userInfo){
        BaseApiEntity baseApiEntity = new BaseApiEntity();

        //获取当前登录用户信息
        String username = userInfo.getSysUserName();
        baseApiEntity.setUsername(username);
        baseApiEntity.setCreateBy(username);
        baseApiEntity.setUpdateBy(username);

        LoginUser loginUser = sysBaseAPI.getUserByName(username); //.getUserById() 获取登录用户
        baseApiEntity.setLoginUser(loginUser);
        String sysOrgCode = loginUser.getOrgCode();//获取当前用户的当前的部门编码（不是id是编码）,该编码随前端切换
        String tenantId = oConvertUtils.isEmpty(userInfo.getTenantId()) ? TenantContext.getTenant() : userInfo.getTenantId();//获取当前登录用户的租户id
//        String tenantId = oConvertUtils.isEmpty(loginUser.getTenantId()) ? TenantContext.getTenant() : loginUser.getTenantId();//获取当前登录用户的租户id
//        TenantContext.setTenant(tenantId);//重新设置租户id

//        String schoolYearId = req.getHeader("school-year-id");//获取当前登录系统选择的学年
//        String semesterId = req.getHeader("semester-id");//获取当前登录系统选择的学期
//        baseApiEntity.setTenantId(tenantId);
//        baseApiEntity.setSchoolYearId(schoolYearId);
//        baseApiEntity.setSemesterId(semesterId);

//        TenantContext.setTenant(tenantId);//重新设置租户id

        String departId = sysBaseAPI.getDepartIdsByOrgCode(sysOrgCode);//获取当前用户设置的部门id
        List<String> subDepIdsList = sysBaseAPI.getSubDepIdsByDepId(departId); //获取下级部门的部门id，自定义改造sysBaseAPI

        baseApiEntity.setSysOrgCode(sysOrgCode);
        baseApiEntity.setSubDepIdsList(subDepIdsList);
        String subDepSysOrgCodes = sysBaseAPI.getSubDepOrgCodesByDepId(departId); //直接获取下级部门的orgcode，自定义改造sysBaseAPI
        baseApiEntity.setSubDepSysOrgCodes(subDepSysOrgCodes);
        //userIdentity 用户身份字典码user_identity， 3教师 4学生 1普通用户 2上级部门负责人 5家长 6班级
        int userIdentity = loginUser.getUserIdentity();//获取当前登录用户身份：字典码 user_identity
        baseApiEntity.setUserIdentity(userIdentity);
        return baseApiEntity;
    }
    /**
     * （通常是用vo接收参数）组装查询参数，组装vo以外的其他参数，一般不用
     * @param req
     * @return
     */
    @Override
    public Map<String,String> getMapQueryParamByReq(HttpServletRequest req){
        //组装vo以外的其他参数
        Map<String,String[]> queryParamArray = req.getParameterMap();
        Map<String,String> queryParam = new HashMap<String,String>();
        queryParam = new HashMap<String,String>();
        for (Map.Entry<String,String[]> entry : queryParamArray.entrySet()) {
            //不知道为什么，传入参数自带**，需替换
            String queryParamValue = entry.getValue()[0];
            queryParamValue = queryParamValue.replace("*","");
            String key = entry.getKey();
            if(entry.getValue().length ==0 || "".equals(entry.getValue()[0]) ){
                continue;
            }
            else if(oConvertUtils.isNotEmpty(queryParam.get(key))){
                //如果参数值已经存在：同名变量重复传参时用逗号间隔
                queryParam.put( key ,queryParam.get(key)+","+queryParamValue );
            }
            else{
                queryParam.put( key ,queryParamValue );
            }

        }
        return queryParam;
    }
}
